win10实现开机播放视频

您所在的位置:网站首页 omnifocus 3开机视频 win10实现开机播放视频

win10实现开机播放视频

2023-07-19 15:50| 来源: 网络整理| 查看: 265

  事先说明本文技术上没有什么发明,大多数是网上能找的到,更多是记录贴而不是技术创新。另外我不是windows方向而是android,当然这不是借口,只是如果可以不用windows高手专家的标准来批判的话,你可以少生一点“什么Windows烂文”的气,我的玻璃心也可以少一点郁闷,大概算皆大欢喜吧。

  最近得到一个任务要弄一个win10平板上的开机视频播放,而且是用户刚拿到的机子,连win10系统第一次进入的设置都还没做过的机子,要让它第一次开机(包括设置过程)和后面开机都能一进去就全屏播放需要它播放的视频。

  像我这样没怎么接触windows开发应该一开始想到的就是直接写个BAT或者VBS,然后放到“启动”目录下就好了。直接在“运行”里输入“shell:startup”,就能找到“启动”目录。最初的应急版本我也确实是这么做的,当然后面改用系统服务启动的方式,如果只是想看基于系统服务的直接跳过一就好。还有win10的“启动”目录如果要通过文件夹点击方式找的话,把hide Item勾选上,因为是在隐藏文件夹里,具体目录是:C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup。

一、基于开机启动项的方式

我的vbs代码是这样的

Set shell = Wscript.createobject("wscript.shell") shell.Run("""C:\Program Files\Windows Media Player\wmplayer.exe"" ""C:\Windows\ANTHEM.mp4"" -fullscreen""") WScript.Sleep 2000 shell.sendKeys "{UP}{UP}{enter}" WScript.Sleep 2000 shell.sendKeys "%{TAB}" WScript.Sleep 127000 CreateObject("WScript.Shell").Run "taskkill /f /im wmplayer.exe", 0

  使用上前面已经讲过就是把vbs放入开机启动项目录里,需要说明一下为什么这样。之所以用windows media player不是因为我多喜欢他,只是这是一个刚刚安装的原始系统,除了“movies & TV”(中文版就是:电影和电视)就是media player。至于为什么不用"movies & TV"来播放,当时确实纠结过,原因很乱,比如我找到的“movies & TV”播放目录里的是需要在什么“应用容器上下文中运行”的,如果有知道怎么可以用vbs运行,请不吝指教。如果直接用vbs不指定播放器来播放,那么第一次播放会用media player,而第二次播放又变成“movies & TV”(或者是反过来)。还有一个原因“movies & TV”的全屏播放快捷键是什么我不知道(知道的也请教一下),当然可以通过按键模拟来实现,但是总是又多了一些不稳定隐患。这条运行wmplayer的命令一开始可不是这样的,正如我说的我的vbs也就是初学者水平,media player的快捷键有-fullscreen一开始也不知道,这是后来不断搜索和修改的结果。

  然后解释一下下面的模拟按键是怎么回事,"{UP}{UP}{enter}"是因为要解决media player第一次播放会弹出的设置框,想看的可以自己在自己的windows机子上运行"C:\Program Files\Windows Media Player\setup_wm.exe",如果你的windows上有media player没被你毁掉的话,就能看见了。模拟按键的效果就是选中“推荐设置”然后确定。

  "%{TAB}"是为了应对,win10用户开机后切换到平板模式,然后关机再开机,这个时候进入的是平板模式,前面做的全屏播放,这个时候只会再后面的windows界面播放,而平板开机看到的界面看不到,所以需要用这个模拟按键,把视频切换出来。

  最后一条命令是为了让视频播放完能自动关闭。

  基于开机启动项模式确实太初学者,就讲这些了,主要要记录一下基于windows系统服务的方法。

二、基于windows系统服务的方式

  用这种方式是因为一的方式太慢,用系统服务就快了。代码用的是C#,一开始也是在C++和C#中间游离,最后决定就用C#,主要是2里得到现成的C#的方案,而这个方案解决了一个关键问题。

1.注册系统服务程序   首先是如何注册系统服务程序,这个没什么可说百度或者谷歌“C#注册系统服务”,我的代码除了自己的需求都和别人的没两样。说点自己试验的过程中遇过的问题。“添加安装程序”这一步后,得到的serviceInstaller里的serviceName属性的命名必须和你的系统服务cs文件里的base.ServiceName = "**";要一致,以及在你的service.cs里一定要有base.ServiceName = "**",否则都无法注册系统服务。而serviceprocessInstaller里的Account最好用LocalSystem,否则可能出现你注册了自启动服务,但是服务却没有开机启动。 2.会话0隔离的突破   注册里系统服务后发现无论如何都无法播放视频,这个问题发现之后花了不少时间来找答案,最后才知道原来windows自从vista以来就开始有会话0隔离。直接效果上说就是你注册的自定义的系统服务打开的GUI界面在我们开机看到的界面里是看不到的,如果你不突破session 0的话,不管你怎么设置这个服务的属性,sc命令了如指掌也没用。而这个问题对我很关键,如果不能看到视频播放界面,那用系统服务就没用了。这里有一篇C#突破会话0隔离的文章,我就是借鉴的这个方法,就不敢卖弄了,直接给大牛的链接:点击打开链接。(如果对链接文章有什么感悟希望能来这里指点一二) 3.分了第一次开机和非第一次的两个脚本   虽然采用了系统服务的方式来实现开机视频播放,但是media player第一次启动的设置界面还是不知道怎么通过代码来跳过所以还是只能通过模拟按键,所以还是在OnStart里调用脚本来执行,为了方便,就加了个count.txt文件里面存放了是否是第一次开机的数值,自定义的系统服务程序读取这个值(第一次会修改值)来判断是否第一次开机,根据这个调用不同脚本。第一次运行的脚本里有“{UP}{UP}{enter}”来解决media player的设置问题,另一个脚本就没有。 4.Win10关机后重新开机无法启动服务   改用系统服务方式后脚本还需要重新调试修改,这个只是时间问题,但是发现了新的问题,注册的系统服务,在restart的情况下开机能重启,但是选“关机”再开机,我自定义的系统服务不会有变化,就是没有重启。这个问题也很关键虽然问题不大但是不能解决就等于前功尽弃。我看来问题应该是因为win10的关机和win8类似属于“混合式关机”。相当于进入休眠而不是真正的关机所以系统服务的状态“关机”前后没有变化,而我需要的是它能重启才能实现视频再次开机播放。最后我也没找到怎么注册系统服务能让这个服务在“关机”后再开机的情况下也能重启,所以用了很不地道的“取消快速开机”的方法。可以手动来做,但是为了让安装人员方便一点,我直接加到intall.bat脚本里在注册系统服务的同时取消掉,powercfg /h off。同时在unintall.bat里重新开启,你不需要开机播放视频了也就不用取消“快速开机”了。如果有人知道怎么不用取消快速开机就能实现的肯教一下,我会非常开心。 5.开机第一次设置的时间不确定造成WTSQueryUserToken函数错误

  前面说了把第一次开机和后面开机分出两个脚本来执行,就是为了分别对待第一次开机和以后开机。但是win10第一次开机进行用户设置的过程中,我注册的系统服务就启动了,虽然在以后开机中这个不但不是问题而且正是我需要的更快开机播放,但是在第一次开机是灾难,不但设置完了之后看不到视频播放,而且在设置过程中如果时间耽误比预期长,为突破session 0的函数WTSQueryUserToken会执行失败。如果在服务程序里直接Thread.sleep休眠来延后我的系统服务启动时间,这样太不靠谱,因为也许用户第一次开机设置一半去上厕所,或者玩去了呢。

  所以还是得找到能判断用户是否进入桌面界面,再启动我的系统服务。我一开始没找到这个API,所以想用进程来判断,一开始想的是“explorer.exe”。但是实验发现这个进程也是在用户设置的过程中已经启动,最后终于找到方法,找到那个用户设置相关的进程,判断这个进程是否结束再启动脚本。

  但是我不知道用户设置究竟是什么进程,所以只好在系统服务中读取用户设置过程中的进程列表和用户设置结束后的进程列表。(当然这靠的是前面调试的结果做的)

public void readProcess(String path) { System.Diagnostics.Process[] processList = System.Diagnostics.Process.GetProcesses(); if (processList != null) { foreach (System.Diagnostics.Process process in processList) { WriteTxt(path, process.ProcessName.ToString()); } } }这个是用来读取进程列表的代码。

  得到两个进程列表文件,我开始比较了,在用户设置结束的进程列表里发现了“searchui”,我马上想如果改判断这个进程也许直接能判断是否已经进入桌面界面,就不需要找运行用户设置这个进程了。但是结果发现这个进程也在用户设置没结束就启动了。

代码虽然大同小异,还是贴一下:

while (!flag) { processList = System.Diagnostics.Process.GetProcesses(); if (processList != null) { foreach (System.Diagnostics.Process process in processList) { if (process.ProcessName.ToLower() == "searchui") { flag = true; name = process.ProcessName.ToString(); break; } } } Thread.Sleep(1000); }不得不老实点继续找用户设置的相关进程,最后找到

if (process.ProcessName.ToString() == "FirstLogonAnim" || process.ProcessName.ToString() == "LogonUI") { flag = true; break; }这两个进程,为了保险全用了,最后总算能在用户进入系统界面后再调用视频播放脚本。   说的这么罗嗦,不是全无用处至少知道哪些进程在第一次开机的用户设置阶段就会启动了。另外svchost.exe这个进程在explorer.exe之前就运行了, “ searchui ”虽然没有找证明,但是应该是在"explorer.exe"后调用的。这个博客里的图虽然对我这次的需求没帮助,但是如果是对windows进程启动顺序有兴趣的不妨参考下:点击打开链接 6.播放无法全屏问题

正如前面脚本代码所示的:

shell.Run("""C:\Program Files\Windows Media Player\wmplayer.exe"" ""C:\WindowService\ANTHEM.mp4"" -fullscreen""")  在基于系统服务的方式下这样直接用参数全屏打开,视频播放器会自动执行切换而退出全屏回复原来大小,同时看到任务栏里不断黄色的闪动。不能直接全屏播放也是个不小的问题,当然最后还是可以在脚本里通过模拟按键解决,但是能找个好点的解决方法总是比较放心。我一开始的想法是突破会话隔离的控制后焦点不能集中到打开的GUI界面,搜索了一下貌似找到专业点的说法:Session 0的进程启动的GUI无法前置。而先运行一个中间进程再由中间进程启动GUI就没有这个问题。

  当然是弹出越少窗口越好,中间进程我简单地用了控制台程序调用:

ShellExecute(IntPtr.Zero, "open", @"C:\\Program Files\\Windows Media Player\\wmplayer.exe", @"C:\WindowService\ANTHEM.mp4 -fullscreen", "", ShowCommands.SW_SHOWNORMAL);  为了不显示黑色的CMD窗口记得在项目的属性里的输出类型选择“Windows应用程序”。

  这样就不用在脚本里通过模拟按键的方式让视频播放器全屏播放了。

      



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3